/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#pragma once

#include "TemporalBlendPass.h"

enum AAMode
{
    AA_MODE_NONE=0,                // no temporal aa
    AA_MODE_MSAA_2X,               // 2x hardware msaa
    AA_MODE_MSAA_4X,               // 4x hardware msaa
    AA_MODE_TEMPORAL_2X            // 2x temporal aa
};

/**
    @brief  Camera information.
            DXUT's CBaseCamera doesn't have accessors for fFov and fAspect. 
    @author yakiimo02
    @date   2010/09/26
*/
struct CameraInfo
{
    float fNear;
    float fFar;
    float fFov;
    float fAspect;
    float fBackBufferW;
    float fBackBufferH;
};

/**
    @brief  Temporal AA.
    @author yakiimo02
    @date   2010/09/24
*/
class TemporalAA
{
public:
    // TEXTURE_NUM=3 won't work without modifying other parts of the code.
    enum { TEXTURE_NUM=2 };
    enum { MSAA_2X=0, MSAA_4X, MSAA_NUM };

public:
    TemporalAA();
    ~TemporalAA();

    HRESULT OnCreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );
    HRESULT OnResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );

    void    OnReleasingSwapChain();
    void    OnDestroyDevice();

    void    SwapFrame() { m_nFrame = (m_nFrame+1)%TEXTURE_NUM; }

    void    BeginRenderScene( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );
    void    EndRenderScene( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext );

    void    BeginTemporalBlendPass( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );
    void    DoTemporalBlendPass( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );
    void    EndTemporalBlendPass( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext );

    D3DXMATRIX GetProjectionJitterMatrix( const CameraInfo& cameraInfo ) const;

    inline  AAMode GetMode() const { return m_mode; }
    inline  void SetMode( AAMode mode ) { m_mode = mode; }

protected:
    D3DXMATRIX JitteredFrustum( float left, float right, float bottom, 
                float top, float near, float far, float pixdx, 
                float pixdy, float eyedx, float eyedy, float focus, const CameraInfo& cameraInfo ) const;

    D3DXMATRIX JitteredPerspective( float fovy, float aspect, 
                                    float near, float far, float pixdx, float pixdy, 
                                    float eyedx, float eyedy, float focus, const CameraInfo& cameraInfo ) const;

protected:
    // Scene texture data 
    ID3D11Texture2D*             m_pSceneTexture[ TEXTURE_NUM ];
    ID3D11ShaderResourceView*    m_pSceneTextureSRV[ TEXTURE_NUM ];
    ID3D11RenderTargetView*      m_pSceneTextureRTV[ TEXTURE_NUM ];
    D3D11_TEXTURE2D_DESC         m_sceneTextureTexDesc;

    // Scene depth stencil data
    ID3D11Texture2D*             m_pDepthTexture;
    ID3D11DepthStencilView*      m_pDSV;

    // MSAA Scene texture data
    ID3D11Texture2D*             m_pSceneTexture_MS[ MSAA_NUM ];
    ID3D11RenderTargetView*      m_pSceneTextureRTV_MS[ MSAA_NUM ];

    // MSAA Scene depth stencil data
    ID3D11Texture2D*             m_pDepthTexture_MS[ MSAA_NUM ];
    ID3D11DepthStencilView*      m_pDSV_MS[ MSAA_NUM ];

    //
    int                          m_nFrame;                                              // 0 or 1
    D3D11_VIEWPORT               m_vpOld[D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX];
    TemporalBlendPass            m_temporalBlendPass;
    AAMode                       m_mode;
};

extern TemporalAA g_temporalAA;

